#include "StringParser.h"
#include "../Settings/Settings.h"
#include "../Logger/Logger.h"
#include "../Model/GameModel.h"
#include <string>
#include <sstream>
#include <stdlib.h>

const char StringParser::separator_ = '$';

int StringParser::readToSeparator(std::string &help, int &pos)
{
  //log("READ TO SEPARATOR");
  while(buffer_[pos] != separator_)
  {
    if (pos > buffer_.size())
    {
      //log("POS IS");
      log(pos, DEBUG);
     // log("BUFFER SIZE IS");
      log(buffer_.size(), DEBUG);
      return 1;
    }

    help += buffer_[pos];
    ++pos;
  }
  return 0;
}

int StringParser::readStartCommand()
{
  log("READ START COMMAND");
  int error = 0;
  int num = 0;
  for (int counter = 0; counter != GameModel::CARDS_NUM_; ++counter)
  {
    error = readNum(num);
    if (error > 0)
    {
      return error;
    }
    cards_[counter].setID(num);
    ++curPos_;

    error = readNum(num);
    if (error > 0)
    {
      return error;
    }
    cards_[counter].setColor(num);
    ++curPos_;
  }
  return 0;
}
 
int StringParser::readNum(int &num)
{
  //log("READ NUM");
  std::string help = "";
  int error = readToSeparator(help, curPos_);
  if (error > 0)
  {
    return error;
  }
  num = atoi(help.c_str());
  //log("NUM IS");
  //log(num, DEBUG);
  return 0;
}

StringParser::StringParser(): buffer_(""), curPos_(0), playerNumber_(0), command_(NO),
                              playerName_(""), settings_(Settings::getInstance())
{
  commandTable_[settings_.get("CONNECT_COMMAND")] = CONNECT;
  commandTable_[settings_.get("CONNECT_CONFIRM_COMMAND")] = CONNECT_CONFIRM;
  commandTable_[settings_.get("START_COMMAND")] = START;
  commandTable_[settings_.get("OPEN_CARD_COMMAND")] = OPEN_CARD;
  commandTable_[settings_.get("GET_TOTEM_COMMAND")] = GET_TOTEM;
  commandTable_[settings_.get("QUIT_COMMAND")] = QUIT;
 
  cards_.resize(GameModel::CARDS_NUM_);
}


int StringParser::parseBuffer()
{
  bool flag = false;
  int i = curPos_;
  log("START_PARSING");
 
  if(i >= buffer_.size())
  {
    return 1;
  }
 
  if (buffer_[i] != separator_)
  {
    return 1;
  }
  ++i;
  std::string help = "";
 
  log("READ_COMMAND"); 
  //read command
  int error = readToSeparator(help, i);
  if (error > 0)
  {
    return error;
  }
  log("END READING COMMAND");
  log("Current command is:");
  log(help);

 
  std::map<std::string, Command>::iterator it = commandTable_.find(help);
  
  log("COMMAND FINDED");
  if (it != commandTable_.end())
  {
    command_ = it->second;
    log("COMMAND SET");
  }
  
  
  
  if (command_ == START)
  {
    curPos_ = i + 1;
    return readStartCommand();
  }
     
  log("READ_PLAYERNUM");
  //read playersNum
  help = "";
  ++i;
  
  error = readToSeparator(help, i);
  if (error > 0)
  {
    return error;
  }

  playerNumber_ = atoi(help.c_str());


  help = "";
  ++i;
  

  log("READ_NAME");

  //read name;
  error = readToSeparator(help, i);
  if (error > 0)
  {
    return error;
  }

  int length = atoi(help.c_str());
  if (length < 0)
  {
    return 1;
  }
  
  help = "";
  ++i;
  for (int j = 0; j != length; j++)
  {
    if (i >= buffer_.size())
    {
      return 0;
    }
    help += buffer_[i];
    ++i;
  }
  
  playerName_ = help;
  curPos_ = i;
  
  log("END_PARSING");  
  return 0;
}



void StringParser::setBuffer(const std::string &buffer)
{
  buffer_ = buffer;
  curPos_ = 0;
}

Command StringParser::getCommand()
{
  return command_;
}


void StringParser::setCommand(Command command)
{
  command_ = command;
}

int StringParser::getPlayerNumber()
{
  return playerNumber_;
}
 
void StringParser::setPlayerNumber(int playerNumber)
{
  playerNumber_ = playerNumber;
}

const std::string& StringParser::getPlayerName()
{
  return playerName_;
}

void StringParser::setPlayerName(const std::string &playerName)
{
  playerName_ = playerName;
}

void StringParser::setParser(Command command, int playerNumber, const std::string &playerName)
{
  command_ = command;
  playerNumber_ = playerNumber;
  playerName_ = playerName;
}

const std::vector<Card>& StringParser::getCards() const
{
  return cards_;
}
